import components.DFA
import SetUp

class LexicalAnalysis:


    def __init__(self, DFASet):
        self.DFASet = DFASet
        self.boundarySymbol = '{}[]()"\';:,'
        self.mathSymbol = '+-*/=&|!'
        self.initSymbol = []
        self.boundary = []
        self.space = []
        self.keySet = [ 'a','b','c','d','e','f','g','h','i','j','k','l','m',
				        'n','o','p','q','r','s','t','u','v','w','x','y','z',
				        'A','B','C','D','E','F','G','H','I','J','K','L','M',
				        'N','O','P','Q','R','S','T','U','V','W','X','Y','Z' ]
        self.keyOrder = ['auto','break','case','char','const','continue','default','false',
                        'do','double','else','enum','extern','float','for','goto',
                        'if','int','long','register','return','short','signed','sizeof','true',
                        'static','struct','switch','typedef','union','unsigned',
                        'void','volatile','while']
        self.boundaryOrder = ['{', '}', '[', ']', '(', ')', '"', '\'', ';', ':', ',']
        self.operatoOrder = ['+','++','+=','-','--','-=','/','<','<=','>','>=','=','==','!=','^','#','%','~','<<','>>','\\','.',':','!']
        self.number = [ '1','2','3','4','5','6','7','8','9','0' ]
        self.hex = [ '1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f','A','B','C','D','E','F' ]


    def analysis(self, text):
        textCopy = text[:]
        self.space = []
        self.boundary = []
        self.initSymbol = []
        for i in range(len(textCopy)):
            if textCopy[i] in self.boundarySymbol:
                self.boundary.append(i)
                self.initSymbol.append(i)
            elif textCopy[i] == ' ':
                self.space.append(i)
                self.initSymbol.append(i)
        self.boundary.append(len(textCopy))
        self.initSymbol.append(len(textCopy))
        index = 0
        indexCopy = 0
        stateStack = []
        symbolStack = []
        DFAStack = []
        wordsStack = []
        kindsStack = []
        hasDFA = False
        DFA = self.DFASet['name']
        # for i in range(59):
        #     print '---------------------'
        #     print i
        while index < len(textCopy):
            # print '---------------------'
            # print len(DFAStack)
            # print index, indexCopy
            # print stateStack
            if index in self.initSymbol and DFA.name != 'note':
                if index in self.boundary:
                    wordsStack.append(textCopy[index])
                    kindsStack.append('boundary')
                index += 1
                indexCopy = index
                continue
            if DFAStack == [] and not hasDFA:
                if textCopy[index] == '_':
                    DFAStack.append(self.DFASet['name'])
                elif textCopy[index] in self.keySet:
                    DFAStack.append(self.DFASet['name'])
                    DFAStack.append(self.DFASet['key1'])
                    DFAStack.append(self.DFASet['key2'])
                    DFAStack.append(self.DFASet['key3'])
                    DFAStack.append(self.DFASet['key4'])
                    DFAStack.append(self.DFASet['key5'])
                elif textCopy[index] in self.number:
                    DFAStack.append(self.DFASet['int'])
                    DFAStack.append(self.DFASet['float'])
                    DFAStack.append(self.DFASet['scien'])
                    DFAStack.append(self.DFASet['hex'])
                elif textCopy[index] == '/':
                    DFAStack.append(self.DFASet['operator'])
                    DFAStack.append(self.DFASet['note'])
                else:
                    # DFAStack.append(self.DFASet['note'])
                    DFAStack.append(self.DFASet['operator'])
            if not hasDFA:
                # print len(DFAStack)
                hasDFA = True
                DFA = DFAStack.pop()
                # DFA.showTransferTable()
            if stateStack == []:
                # print 'init'
                # DFA.showTransferTable()
                isTrans, nextState = DFA.trans(textCopy[indexCopy], 0)
            else:
                if indexCopy not in self.initSymbol:
                    # print 'not in'
                    isTrans, nextState = DFA.trans(textCopy[indexCopy], stateStack[len(stateStack)-1])
                else:
                    # print 'in'
                    if DFA.name != 'note':
                        isTrans = False
                        nextState = False
                    else:
                        if indexCopy != len(textCopy):
                            isTrans, nextState = DFA.trans(textCopy[indexCopy], stateStack[len(stateStack)-1])
                        else:
                            isTrans = False
                            nextState = False
            # print isTrans, nextState
            if isTrans:
                stateStack.append(nextState)
                symbolStack.append(textCopy[indexCopy])
                indexCopy += 1
                # print symbolStack
            else:
                if indexCopy in self.initSymbol:
                    # print stateStack, symbolStack
                    if stateStack[indexCopy-index-1] in DFA.endStates:
                        # print 'true'
                        # print ''.join(symbolStack)
                        wordsStack.append(''.join(symbolStack))
                        kindsStack.append(DFA.name)
                        hasDFA = False
                        DFAStack = []
                        if DFA.name == 'note':
                            DFA.name = ''
                        stateStack = []
                        symbolStack = []
                        index = indexCopy
                    else:
                        # print 'false'
                        # print ''.join(symbolStack)
                        hasDFA = False
                        stateStack = []
                        symbolStack = []
                        if DFAStack == []:
                            index = indexCopy
                        else:
                            indexCopy = index
                else:
                    if DFA.isTransCondition(textCopy[indexCopy]) and len(DFAStack) > 0:
                        hasDFA = False
                        stateStack = []
                        symbolStack = []
                        indexCopy = index
                    else:
                        foundTex = False
                        for i in range(0, len(stateStack)):
                            # print stateStack[len(stateStack)-i-1]
                            if stateStack[len(stateStack)-i-1] in DFA.endStates:
                                # print ''.join(symbolStack[:len(stateStack)-i])
                                wordsStack.append(''.join(symbolStack[:len(stateStack)-i]))
                                kindsStack.append(DFA.name)
                                # print index, indexCopy
                                index = indexCopy
                                # print index, indexCopy
                                foundTex = True
                                break
                        if foundTex:
                            DFAStack = []
                            stateStack = []
                            symbolStack = []
                            hasDFA = False
                        else:
                            stateStack = []
                            symbolStack = []
                            indexCopy = index
                            hasDFA = False
        result = []
        for i in range(len(wordsStack)):
            content = ''
            content += str(wordsStack[i])
            for j in range(25-len(wordsStack[i])):
                content += ' '
            content += '<'
            if str(kindsStack[i]) == 'name':
                content += 'IDN'
            elif str(kindsStack[i]) == 'key1' or str(kindsStack[i]) == 'key2' or str(kindsStack[i]) == 'key3' or str(kindsStack[i]) == 'key4' or str(kindsStack[i]) == 'key5':
                index = self.keyOrder.index(wordsStack[i])
                content += 'key'
                content += str(index + len(self.operatoOrder))
            elif str(kindsStack[i]) == 'operator':
                index = self.operatoOrder.index(wordsStack[i])
                content += 'INC'
                content += str(index)
            elif str(kindsStack[i]) == 'int':
                content += 'INTEGER'
            elif str(kindsStack[i]) == 'float':
                content += 'FLOAT'
            elif str(kindsStack[i]) == 'scien':
                content += 'E-NOTATION'
            elif str(kindsStack[i]) == 'hex':
                content += 'HEX'
            elif str(kindsStack[i]) == 'boundary':
                index = self.boundaryOrder.index(wordsStack[i])
                content += 'BND'
                content += str(index + len(self.keyOrder) + len(self.operatoOrder))
            elif str(kindsStack[i]) == 'note':
                content += 'NOTES'
            for j in range(8-len(kindsStack[i])):
                content += ' '
            content += ','
            if kindsStack[i] == 'name' or kindsStack[i] == 'int' or kindsStack[i] == 'float' or kindsStack[i] == 'hex' or kindsStack[i] == 'scien':
                content += wordsStack[i]
            else:
                content += '_'
            content += '>'
            result.append(content)
            # print content
        return result


    def loadFile(self, filePath):
        inputFile = open(filePath)
        lines = inputFile.readlines()
        content = ''
        for line in lines:
            content += line.split('\n')[0]
        return content

if __name__ == "__main__":
    DFASet = SetUp.loadRegex()
    analysisor = LexicalAnalysis(DFASet)
    # DFASet['operator'].showTransferTable()
    # print DFASet['operator'].endStates
    text = analysisor.loadFile('param/test')
    # analysisor.DFASet['number'].showTransferTable()
    # text = '/**thread sleep**/ '
    # print text
    analysisor.analysis(text)
    # print analysisor.initSymbol, analysisor.space, analysisor.boundary
